package com.terracloud.server.dao.device;

import com.terracloud.server.common.data.device.DeviceAccessControlMode;
import com.terracloud.server.common.data.device.DeviceAccessControlRule;
import com.terracloud.server.common.data.device.DeviceAccessControlRuleType;
import com.terracloud.server.common.data.id.DeviceAccessControlRuleId;
import com.terracloud.server.common.data.id.TenantId;
import com.terracloud.server.common.data.page.PageData;
import com.terracloud.server.common.data.page.PageLink;
import com.terracloud.server.dao.exception.DataValidationException;
import com.terracloud.server.dao.service.DataValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

@Service("DeviceAccessControlRuleDaoService")
@Slf4j
@RequiredArgsConstructor
public class DeviceAccessControlRuleServiceImpl implements DeviceAccessControlRuleService {

    private final DeviceAccessControlRuleDao deviceAccessControlRuleDao;

    @Override
    public DeviceAccessControlRule saveDeviceAccessControlRule(DeviceAccessControlRule rule) {
        ruleValidator.validate(rule, DeviceAccessControlRule::getTenantId);
        return deviceAccessControlRuleDao.save(rule.getTenantId(), rule);
    }

    @Override
    public DeviceAccessControlRule findDeviceAccessControlRuleById(TenantId tenantId, DeviceAccessControlRuleId ruleId) {
        return deviceAccessControlRuleDao.findById(tenantId, ruleId.getId());
    }

    @Override
    public PageData<DeviceAccessControlRule> findAllDeviceAccessControlRules(TenantId tenantId, PageLink pageLink) {
        return deviceAccessControlRuleDao.findAll(pageLink);
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRulesByTextSearch(TenantId tenantId, String textSearch, PageLink pageLink) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            return deviceAccessControlRuleDao.findByTextSearch(textSearch, pageLink);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndTextSearch(tenantId.getId(), textSearch, pageLink);
        }
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRulesByTypeAndTextSearch(TenantId tenantId, String type, String textSearch, PageLink pageLink) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            return deviceAccessControlRuleDao.findByTypeAndTextSearch(type, textSearch, pageLink);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndTypeAndTextSearch(tenantId.getId(), type, textSearch, pageLink);
        }
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRulesByModeAndTextSearch(TenantId tenantId, DeviceAccessControlMode mode, String textSearch, PageLink pageLink) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            return deviceAccessControlRuleDao.findByModeAndTextSearch(mode, textSearch, pageLink);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndModeAndTextSearch(tenantId.getId(), mode, textSearch, pageLink);
        }
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRulesByTypeAndModeAndTextSearch(TenantId tenantId, String type, DeviceAccessControlMode mode, String textSearch, PageLink pageLink) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            return deviceAccessControlRuleDao.findByTypeAndModeAndTextSearch(type, mode, textSearch, pageLink);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndTypeAndModeAndTextSearch(tenantId.getId(), type, mode, textSearch, pageLink);
        }
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRulesByType(TenantId tenantId, String type, PageLink pageLink) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            return deviceAccessControlRuleDao.findByType(type, pageLink);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndType(tenantId.getId(), type, pageLink);
        }
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRulesByMode(TenantId tenantId, DeviceAccessControlMode mode, PageLink pageLink) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            return deviceAccessControlRuleDao.findByMode(mode, pageLink);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndMode(tenantId.getId(), mode, pageLink);
        }
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRulesByTypeAndMode(TenantId tenantId, String type, DeviceAccessControlMode mode, PageLink pageLink) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            return deviceAccessControlRuleDao.findByTypeAndMode(type, mode, pageLink);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndTypeAndMode(tenantId.getId(), type, mode, pageLink);
        }
    }

    @Override
    public PageData<DeviceAccessControlRule> findDeviceAccessControlRules(TenantId tenantId, PageLink pageLink) {
        return deviceAccessControlRuleDao.findByTenantId(tenantId.getId(), pageLink);
    }

    @Override
    public DeviceAccessControlRule findDeviceAccessControlRuleByValue(TenantId tenantId, String value) {
        if (tenantId == null || tenantId.isNullUid() || tenantId.getId().equals(new UUID(0L, 0L))) {
            // 查询所有租户的规则
            // 由于Repository没有提供查询所有租户规则的方法，我们暂时只查询默认租户的规则
            // 在实际应用中，可能需要修改Repository接口来支持跨租户查询
            return deviceAccessControlRuleDao.findByTenantIdAndValue(new UUID(0L, 0L), value);
        } else {
            // 查询特定租户的规则
            return deviceAccessControlRuleDao.findByTenantIdAndValue(tenantId.getId(), value);
        }
    }
    
    @Override
    public List<DeviceAccessControlRule> findDeviceAccessControlRulesByValueAndType(String value, DeviceAccessControlRuleType type) {
        return deviceAccessControlRuleDao.findByValueAndType((String) value, (DeviceAccessControlRuleType) type);
    }

    @Override
    public void deleteDeviceAccessControlRule(TenantId tenantId, DeviceAccessControlRuleId ruleId) {
        deviceAccessControlRuleDao.removeById(tenantId, ruleId.getId());
    }

    private final DataValidator<DeviceAccessControlRule> ruleValidator =
            new DataValidator<>() {
                @Override
                protected void validateDataImpl(TenantId tenantId, DeviceAccessControlRule rule) {
                    if (rule.getTenantId() == null) {
                        throw new DataValidationException("Device access control rule should be assigned to tenant!");
                    }
                    if (rule.getType() == null) {
                        throw new DataValidationException("Device access control rule type should be specified!");
                    }
                    if (rule.getValue() == null || rule.getValue().isEmpty()) {
                        throw new DataValidationException("Device access control rule value should be specified!");
                    }
                    if (rule.getMode() == null) {
                        throw new DataValidationException("Device access control rule mode should be specified!");
                    }
                }

                @Override
                protected void validateCreate(TenantId tenantId, DeviceAccessControlRule rule) {
                    // 检查是否已存在相同值的规则
                    DeviceAccessControlRule existingRule = findDeviceAccessControlRuleByValue(rule.getTenantId(), rule.getValue());
                    if (existingRule != null) {
                        // 如果是更新操作，允许更新自身
                        if (rule.getId() == null || !rule.getId().equals(existingRule.getId())) {
                            throw new DataValidationException("Device access control rule with such value already exists!");
                        }
                    }
                }

                @Override
                protected DeviceAccessControlRule validateUpdate(TenantId tenantId, DeviceAccessControlRule rule) {
                    DeviceAccessControlRule existingRule = findDeviceAccessControlRuleById(rule.getTenantId(), rule.getId());
                    if (existingRule == null) {
                        throw new DataValidationException("Device access control rule with such id does not exist!");
                    }
                    // 检查当值发生变化时，新值是否与其他规则冲突
                    if (!existingRule.getValue().equals(rule.getValue())) {
                        DeviceAccessControlRule conflictingRule = findDeviceAccessControlRuleByValue(rule.getTenantId(), rule.getValue());
                        if (conflictingRule != null) {
                            // 如果是更新操作，允许更新自身
                            if (!rule.getId().equals(conflictingRule.getId())) {
                                throw new DataValidationException("Device access control rule with such value already exists!");
                            }
                        }
                    }
                    return existingRule;
                }
            };
}